package nl.cwi.arne.diagram.parsers;

import java.util.StringTokenizer;

import nl.cwi.arne.Edge;

import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.emf.transaction.util.TransactionUtil;
import org.eclipse.gmf.runtime.common.core.command.CommandResult;
import org.eclipse.gmf.runtime.common.core.command.ICommand;
import org.eclipse.gmf.runtime.common.core.command.UnexecutableCommand;
import org.eclipse.gmf.runtime.common.ui.services.parser.IParserEditStatus;
import org.eclipse.gmf.runtime.common.ui.services.parser.ParserEditStatus;
import org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand;

/**
 * @generated NOT
 * @author Christian Krause
 */
public class EdgeConstraintParser extends AbstractParser {
	
	private static final String ARROW = "->";
	
	/**
	 * Default constructor.
	 */
	public EdgeConstraintParser() {
		super(new EAttribute[] {});
	}
	
	/*
	 * (non-Javadoc)
	 * @see org.eclipse.gmf.runtime.common.ui.services.parser.IParser#getEditString(org.eclipse.core.runtime.IAdaptable, int)
	 */
	public String getEditString(IAdaptable element, int flags) {
		Edge edge = (Edge) element.getAdapter(EObject.class);
		if (!edge.getBaseLevels().isEmpty()) {
			
			// Up / downward closed?
			if (edge.isUpClosed()) {
				return "+" + edge.getMinBaseLevel();
			}
			if (edge.isDownClosed()) {
				return "-" + (edge.getMaxBaseLevel()+1);
			}
			
			// Otherwise list notation:
			String result = edge.getBaseLevels().get(0).toString();
			for (int i=1; i<edge.getBaseLevels().size(); i++) {
				result = result + "," + edge.getBaseLevels().get(i);
			}
			return result;
		}
		else {
			return edge.getStartLevel() + ARROW + edge.getEndLevel();
		}
	}
	
	/*
	 * (non-Javadoc)
	 * @see org.eclipse.gmf.runtime.common.ui.services.parser.IParser#getPrintString(org.eclipse.core.runtime.IAdaptable, int)
	 */
	public String getPrintString(IAdaptable element, int flags) {
		return getEditString(element, flags);
	}

	/*
	 * (non-Javadoc)
	 * @see org.eclipse.gmf.runtime.common.ui.services.parser.IParser#getParseCommand(org.eclipse.core.runtime.IAdaptable, java.lang.String, int)
	 */
	public ICommand getParseCommand(IAdaptable element, final String value, int flags) {
		
		// Resolve the action:
		final Edge action = (Edge) element.getAdapter(EObject.class);
		
		// Get the editing domain:
		TransactionalEditingDomain editingDomain = TransactionUtil.getEditingDomain(action);
		if (editingDomain == null) {
			return UnexecutableCommand.INSTANCE;
		}
		
		// Create parse command:
		AbstractTransactionalCommand command = new AbstractTransactionalCommand(editingDomain, "Parse Level Constraint", null) {
			protected CommandResult doExecuteWithResult(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
				return doParsing(value, action);
			}
		};
		return command;
		
	}

	/*
	 * Parse an action.
	 */
	private CommandResult doParsing(String value, Edge edge) {
		
		// Reset and parse.
		edge.getBaseLevels().clear();
		edge.setStartLevel(0);
		edge.setEndLevel(0);
		
		try {
			value = value.trim();
			if (value.startsWith("+")) {
				value = value.substring(1).trim();
				int min = Integer.parseInt(value);
				for (int i=min; i<edge.getSource().getLevels(); i++) {
					edge.getBaseLevels().add(i);
				}
			}
			else if (value.startsWith("-")) {
				value = value.substring(1).trim();
				int max = Integer.parseInt(value);
				for (int i=0; i<max; i++) {
					edge.getBaseLevels().add(i);
				}
			}
			else {
				int index = value.indexOf(ARROW);
				if (index>=0) {
					edge.setStartLevel(Integer.valueOf(value.substring(0,index)));
					edge.setEndLevel(Integer.valueOf(value.substring(index+2)));
				} else {
					StringTokenizer tokenizer = new StringTokenizer(value, ",");
					while (tokenizer.hasMoreTokens()) {
						edge.getBaseLevels().add(Integer.parseInt(tokenizer.nextToken()));
					}
				}
			}
		} catch (Exception e) {
			return CommandResult.newErrorCommandResult(e);
		}
		
		return CommandResult.newOKCommandResult();
		
	}
	
	/*
	 * (non-Javadoc)
	 * @see org.eclipse.gmf.runtime.common.ui.services.parser.IParser#isValidEditString(org.eclipse.core.runtime.IAdaptable, java.lang.String)
	 */
	public IParserEditStatus isValidEditString(IAdaptable element, String editString) {
		return ParserEditStatus.EDITABLE_STATUS;
	}
	
	/*
	 * (non-Javadoc)
	 * @see nl.cwi.arne.diagram.parsers.AbstractParser#isAffectingFeature(java.lang.Object)
	 */
	@Override
	protected boolean isAffectingFeature(Object feature) {
		return true;
	}

}
